--- sys/dev/virtio/pci/virtio_pci_legacy.c.orig
+++ sys/dev/virtio/pci/virtio_pci_legacy.c
@@ -59,8 +59,10 @@
 struct vtpci_legacy_softc {
 	device_t			 vtpci_dev;
 	struct vtpci_common		 vtpci_common;
+	int				 vtpci_res_type;
 	struct resource			*vtpci_res;
-	struct resource			*vtpci_msix_res;
+	struct resource			*vtpci_msix_table_res;
+	struct resource			*vtpci_msix_pba_res;
 };
 
 static int	vtpci_legacy_probe(device_t);
@@ -97,6 +99,8 @@
 static void	vtpci_legacy_read_dev_config(device_t, bus_size_t, void *, int);
 static void	vtpci_legacy_write_dev_config(device_t, bus_size_t, void *, int);
 
+static bool	vtpci_legacy_setup_msix(struct vtpci_legacy_softc *sc);
+static void	vtpci_legacy_teardown_msix(struct vtpci_legacy_softc *sc);
 static int	vtpci_legacy_alloc_resources(struct vtpci_legacy_softc *);
 static void	vtpci_legacy_free_resources(struct vtpci_legacy_softc *);
 
@@ -228,10 +232,17 @@
 
 	error = vtpci_legacy_alloc_resources(sc);
 	if (error) {
-		device_printf(dev, "cannot map I/O space\n");
+		device_printf(dev, "cannot map I/O space nor memory space\n");
 		return (error);
 	}
 
+	if (vtpci_is_msix_available(&sc->vtpci_common) &&
+	    !vtpci_legacy_setup_msix(sc)) {
+		device_printf(dev, "cannot setup MSI-x resources\n");
+		error = ENXIO;
+		goto fail;
+	}
+
 	vtpci_legacy_reset(sc);
 
 	/* Tell the host we've noticed this device. */
@@ -265,6 +276,7 @@
 		return (error);
 
 	vtpci_legacy_reset(sc);
+	vtpci_legacy_teardown_msix(sc);
 	vtpci_legacy_free_resources(sc);
 
 	return (0);
@@ -539,25 +551,77 @@
 	}
 }
 
+static bool
+vtpci_legacy_setup_msix(struct vtpci_legacy_softc *sc)
+{
+	device_t dev;
+	int rid, table_rid;
+
+	dev = sc->vtpci_dev;
+
+	rid = table_rid = pci_msix_table_bar(dev);
+	if (rid != PCIR_BAR(0)) {
+		sc->vtpci_msix_table_res = bus_alloc_resource_any(
+		    dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+		if (sc->vtpci_msix_table_res == NULL)
+			return (false);
+	}
+
+	rid = pci_msix_pba_bar(dev);
+	if (rid != table_rid && rid != PCIR_BAR(0)) {
+		sc->vtpci_msix_pba_res = bus_alloc_resource_any(
+		    dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+		if (sc->vtpci_msix_pba_res == NULL)
+			return (false);
+	}
+
+	return (true);
+}
+
+static void
+vtpci_legacy_teardown_msix(struct vtpci_legacy_softc *sc)
+{
+	device_t dev;
+
+	dev = sc->vtpci_dev;
+
+	if (sc->vtpci_msix_pba_res != NULL) {
+		bus_release_resource(dev, SYS_RES_MEMORY,
+		    rman_get_rid(sc->vtpci_msix_pba_res),
+		    sc->vtpci_msix_pba_res);
+		sc->vtpci_msix_pba_res = NULL;
+	}
+	if (sc->vtpci_msix_table_res != NULL) {
+		bus_release_resource(dev, SYS_RES_MEMORY,
+		    rman_get_rid(sc->vtpci_msix_table_res),
+		    sc->vtpci_msix_table_res);
+		sc->vtpci_msix_table_res = NULL;
+	}
+}
+
 static int
 vtpci_legacy_alloc_resources(struct vtpci_legacy_softc *sc)
 {
+	const int res_types[] = { SYS_RES_IOPORT, SYS_RES_MEMORY };
 	device_t dev;
-	int rid;
+	int rid, i;
 
 	dev = sc->vtpci_dev;
 	
-	rid = PCIR_BAR(0);
-	if ((sc->vtpci_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
-	    &rid, RF_ACTIVE)) == NULL)
-		return (ENXIO);
-
-	if (vtpci_is_msix_available(&sc->vtpci_common)) {
-		rid = PCIR_BAR(1);
-		if ((sc->vtpci_msix_res = bus_alloc_resource_any(dev,
-		    SYS_RES_MEMORY, &rid, RF_ACTIVE)) == NULL)
-			return (ENXIO);
+	/*
+	 * Most hypervisors export the common configuration structure in IO
+	 * space, but some use memory space; try both.
+	 */
+	for (i = 0; nitems(res_types); i++) {
+		rid = PCIR_BAR(0);
+		sc->vtpci_res_type = res_types[i];
+		sc->vtpci_res = bus_alloc_resource_any(dev, res_types[i], &rid,
+		    RF_ACTIVE);
+		if (sc->vtpci_res != NULL)
+			break;
 	}
+	if (sc->vtpci_res == NULL)
+		return (ENXIO);
 
 	return (0);
 }
@@ -569,14 +633,8 @@
 
 	dev = sc->vtpci_dev;
 
-	if (sc->vtpci_msix_res != NULL) {
-		bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(1),
-		    sc->vtpci_msix_res);
-		sc->vtpci_msix_res = NULL;
-	}
-
 	if (sc->vtpci_res != NULL) {
-		bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0),
+		bus_release_resource(dev, sc->vtpci_res_type, PCIR_BAR(0),
 		    sc->vtpci_res);
 		sc->vtpci_res = NULL;
 	}
